import sys
#from sets import Set
from decimal import *
import random as R

#emptySet = Set([])

def validateInputs(reqType, input):
    valid = True
    try:
        if type(reqType)==str and \
           ((reqType=='multiple of 1000' and (type(input)!=int or (input % 1000))) \
            or \
           (reqType=='string' and type(input)!=str)):
            valid = 'Sorry, _ must be a ' + reqType
        elif type(reqType)==tuple and not (input in reqType):
            valid = 'Sorry, _ must be one of ' + str(reqType)
        elif reqType==int and not type(input)==int:
            valid = 'Sorry, _ must be an int type'
        elif reqType==dict:
            pass
            
    except:
        valid = 'Sorry, exception raised trying to confirm that _ is a ' + reqType
    return valid

class CARD(object):

    def __init__(self, *arg, **karg):
        pass


class Vancard(CARD):
    
    mlist = ('menu')
    plist = ('name', 'clan', 'picture', 'attack', 'shield', 'grade', 'type', 
             'trigger', 'abilities', 'status', 'position', 'race', 'rarity',
             'number')

    def __init__(self, *arg, **karg):
        CARD.__init__(self)
        for key in karg.keys():
            if key in self.plist: 
                exec('self.' + key + ' = karg["' + key + '"]') 

    def __str__(self):
        s = ''
        for p in self.plist:
            if hasattr(self, p):
                s += str((p, str(eval('self.' + p)))) + ', '
        return s[:-2]

  # Name property
    @property 
    def name(self):
        """ Card's name; a string """
        return self._name
    @name.setter
    def name(self, card_name):
        valid = validateInputs('string', card_name)
        if type(valid)==str:
            self._name = valid.replace('_', 'card_name')
        else:
            self._name = card_name
    @name.deleter
    def name(self):
        del self._name

  # Clan property
    @property 
    def clan(self):
        """ Card's clan; a string """
        return self._clan
    @clan.setter
    def clan(self, clan_name):
        valid = validateInputs('string', clan_name)
        if type(valid)==str:
            self._clan = valid.replace('_', 'clan_name')
        else:
            self._clan = clan_name
    @clan.deleter
    def clan(self):
        del self._clan

  # Picture property
    @property 
    def picture(self):
        """ Card's picture; an image """
        return self._imaj    
    @picture.setter
    def picture(self, card_imaj):
      # TODO: add validation
        self._imaj = card_imaj
    @picture.deleter
    def picture(self):
        del self._imaj

  # Attack property
    @property 
    def attack(self):
        """ Card's attack strength; a multiple of 1000 """
        return self._atak    
    @attack.setter
    def attack(self, card_atak):
        valid = validateInputs('multiple of 1000', card_atak)
        if type(valid)==str:
            self._atak = -1
        else:
            self._atak = card_atak
    @attack.deleter
    def attack(self):
        del self._atak

  # Shield property
    @property 
    def shield(self):
        """ Card's shield strength; a multiple of 1000 """
        return self._shld
    @shield.setter
    def shield(self, card_shld):
        valid = validateInputs('multiple of 1000', card_shld)
        if type(valid)==str:
            self._shld = -1
        else:
            self._shld = card_shld
    @shield.deleter
    def shield(self):
        del self._shld
 
  # Grade property
    @property 
    def grade(self):
        """ Card's grade; one of 0, 1, 2, or 3 """
        return self._grad
    @grade.setter
    def grade(self, card_grad):
        valid = validateInputs((0,1,2,3), card_grad)
        if type(valid)==str:
            self._grad = -1
        else:
            self._grad = card_grad
    @grade.deleter
    def grade(self):
        del self._grad

  # Type property
    @property 
    def type(self):
        """ Card's type; one of 'b'(oost), 'g'(uard), or 'd'(rive) """
        return self._type
    @type.setter
    def type(self, card_type):
        valid = validateInputs(('b', 'g', 'd'), card_type)
        if type(valid)==str:
            self._type = -1
        else:
            self._type = card_type
    @type.deleter
    def type(self):
        del self._type

  # Trigger property
    @property 
    def trigger(self):
        """ Card's trigger; a dict with keys 'kind' & 'valu'
            kind's possible values are: 'heal', 'stnd', 'draw', or 'crit'
            valu is typically 5000
        """
        return self._trgr
    @trigger.setter
    def trigger(self, card_trgr):
      # TODO: add validation
        self._trgr = card_trgr
    @trigger.deleter
    def trigger(self):
        del self._trgr

  # Abilities property
    @property 
    def abilities(self):
        """ Card's abilities; a dict with keys 'cost', 'cond', & 'desc'
            cost's possible values are 'counterblast', 'soulblast', 'discard', or 'other'
            cond's & desc's possible values are diverse
        """
        return self._abil    
    @abilities.setter
    def abilities(self, card_abil):
      # TODO: add validation
        self._abil = card_abil
    @abilities.deleter
    def abilities(self):
        del self._abil

  # Status property
    @property 
    def status(self):
        """ Card's status; 'f'(lipped), 't'(apped), or 'r'(eady) """
        return self._stat
    @status.setter
    def status(self, card_stat):
        valid = validateInputs(('f', 't', 'r'), card_stat)
        if type(valid)==str:
            self._stat = -1#valid.replace('_', 'card_stat')
        else:
            self._stat = card_stat
    @status.deleter
    def status(self):
        del self._stat

  # Position property
    @property 
    def position(self):
        """ Card's position; a deck object (see below) """
        return self._posn
    @position.setter
    def position(self, card_posn):
      # TODO: add validation
        self._posn = card_posn
    @position.deleter
    def position(self):
        del self._posn

  # Race property
    @property 
    def race(self):
        """ Card's race; a string """
        return self._race    
    @race.setter
    def race(self, card_race):
        valid = validateInputs('string', card_race)
        if type(valid)==str:
            self._race = valid.replace('_', 'card_race')
        else:
            self._race = card_race
    @race.deleter
    def race(self):
        del self._race


  # Number property
    @property 
    def number(self):
        """ Card's number; an int? """
        return self._nmbr
    @number.setter
    def number(self, card_nmbr):
        valid = validateInputs(int, card_nmbr)
        if type(valid)==str:
            self._nmbr = -1
        else:
            self._nmbr = card_nmbr
    @number.deleter
    def number(self):
        del self._nmbr

  # Rarity property
    @property 
    def rarity(self):
        """ Card's rarity; an int """
        return self._rare
    @rarity.setter
    def rarity(self, card_rare):
        valid = validateInputs(int, card_rare)
        if type(valid)==str:
            self._rare = -1
        else:
            self._rare = card_rare
    @rarity.deleter
    def rarity(self):
        del self._rare

  # Methods
    def menu(self):
        print 'properties (attributes you can get, set, and delete):'
        print self.plist
        print 'methods (functions you can perform):'
        print self.mlist


class STACK(object):

    def __init__(self, cardList=[], stacType=''):
        self.List = cardList
        self.Type = stacType 

    def __str__(self):
        s = self.Type + ':\n'
        for card in self.List:
            s += card.name + '\n'
        return s
        
  # List-of-Cards property
    @property 
    def List(self):
        """ Cards in this stack; a list of CARD objects """
        return self._list
    @List.setter
    def List(self, cardList):
        self._list = []
        if type(cardList) == list:
            for card in cardList:
                if not isinstance(card, CARD):
                    self._list = 'Sorry, ' + str(card) + ' does not appear ' + \
                                 'to be a valid CARD type.  Please check your '\
                                 + 'cards and try again.'
                    break
            if not self._list:
                self._list = cardList
    @List.deleter
    def List(self):
        self._list = []

  # STACK Type property, i.e., 'Deck', 'Hand', etc.
    @property 
    def Type(self):
        """ 'Type' of stack, e.g., 'Deck', 'Hand', 'Field', 'Discard', etc.;
             a string
        """
        return self._type
    @Type.setter
    def Type(self, Type):
        if type(Type) == str:
            self._type = Type
        else:
            self._type = -1
    @Type.deleter
    def Type(self):
        self._type = ''
        
  # Number-of-cards property
    @property 
    def count(self):
        """ Number of cards in this stack """
        return len(self.List)


class Deck(STACK):
    
    def __init__(self, cardList=[]):
        STACK.__init__(self, cardList, 'Deck')


class Hand(STACK):
    
    def __init__(self, cardList=[]):
        STACK.__init__(self, cardList, 'Hand')


class Drop(STACK):
    
    def __init__(self, cardList=[]):
        STACK.__init__(self, cardList, 'Drop')


class Xile(STACK):
    
    def __init__(self, cardList=[]):
        STACK.__init__(self, cardList, 'Xile')
        

class Field(STACK):
    
    def __init__(self, cardList=[], stacType='Field'):
        STACK.__init__(self, cardList, stacType)


class foreField(Field):
    
    def __init__(self, cardList=[]):
        Field.__init__(self, cardList, 'fore')


class mainField(Field):
    
    def __init__(self, cardList=[]):
        Field.__init__(self, cardList, 'main')


class rearField(Field):
    
    def __init__(self, cardList=[]):
        Field.__init__(self, cardList, 'rear')
